package com.jijs.framework.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


/**
 * 字体图标工具类<br>
 * 能够自动加载配置文件中的字体文件，并生成缓存提高工作效率。<br>
 * 使用unicode的方式，解决IE6的兼容性问题
 * 
 * @author jijs
 *
 */
public class IconFontHelper {

	/** 日志对象 */
	private static final Logger LOG = Logger.getLogger(IconFontHelper.class);

	/** 字体缓存 */
	private HashMap<String, String> cache = null;

	private static IconFontHelper helper = null;

	private static final Object LOCK = new Object();

	private static final String SEPERATOR_KEY_VALUE = ":";
	private static final String SEPERATOR_LINE = "\r\n";

	public static IconFontHelper getInstance() throws DocumentException {

		synchronized (LOCK) {

			if (helper == null) {

				synchronized (LOCK) {
					if (helper == null) {
						helper = new IconFontHelper();
					}
				}
			}
		}

		return helper;
	}

	private IconFontHelper() throws DocumentException {

		cache = new HashMap<>();

		init();
	}

	/**
	 * 初始化方法，判断缓存文件是否存在，如果不存在则生成缓存文件。如果缓存文件存在，则直接将缓存文件加载到内存中。
	 * 
	 * @throws DocumentException
	 */
	private void init() throws DocumentException {

		File resources = new File(FileUtils.getWebAppBasePath(), "resources");
		File css = new File(resources, "css");
		File adetheme = new File(css, "ade-theme");
		File icons = new File(adetheme, "icons");

		File cacheFile = new File(icons, "iconfont.ade.cache");

		if (!cacheFile.exists()) {
			// 解析字体文件
			File iconfont = new File(icons, "iconfont.svg");
			parseSource(iconfont);
			saveCache2File(cacheFile);
		} else {
			loadCacheFile(cacheFile);
		}
	}

	/**
	 * 加载缓存文件
	 * 
	 * @param cacheFile
	 */
	private void loadCacheFile(File cacheFile) {

		String content = null;

		try {
			content = FileUtils.readString(cacheFile, "UTF-8");
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}

		String[] lines = content.split(SEPERATOR_LINE);
		for (String line : lines) {
			String[] keyValue = line.split(SEPERATOR_KEY_VALUE);
			cache.put(keyValue[0], keyValue[1]);
		}
	}

	private void saveCache2File(File cacheFile) {

		LOG.debug("缓存字体文件>>" + cacheFile);

		StringBuffer sb = new StringBuffer();

		for (String key : cache.keySet()) {
			sb.append(key + SEPERATOR_KEY_VALUE + cache.get(key));
			sb.append(SEPERATOR_LINE);
		}

		try {
			FileUtils.writeString(sb.toString(), cacheFile, "UTF-8");
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}
	}

	private void parseSource(File iconfont) throws DocumentException {

		SAXReader reader = new SAXReader();
		reader.setEntityResolver(new IgnoreDTDEntityResolver()); // ignore dtd

		Document doc = reader.read(iconfont);

		Element element = doc.getRootElement();

		Element defsElement = element.element("defs");

		Element fontElement = defsElement.element("font");

		@SuppressWarnings("unchecked")
		List<Element> glyphElements = fontElement.elements("glyph");

		for (Element glyphElement : glyphElements) {

			String unicode = glyphElement.attributeValue("unicode");

			if (StringUtil.isEmpty(unicode)) {// 如果unicode没有值，我们不要
				continue;
			}

			String name = glyphElement.attributeValue("glyph-name").trim();

			if ("x".equals(name)) {// 不要名称为x的那个
				continue;
			}

			cache.put(name, "&#x" + Integer.toHexString(unicode.charAt(0)) + ";");
		}
	}

	/**
	 * 获得一个名称的unicode
	 * 
	 * @param name
	 *            名称
	 * @return unicode码
	 */
	public String getUnicode(String name) {
		return cache.get(name);
	}

	/**
	 * 获得名称列表
	 * 
	 * @return 名称列表
	 */
	public Map<String, String> getCacheClone() {

		@SuppressWarnings("unchecked")
		Map<String, String> cloneMap = (Map<String, String>) cache.clone();

		return cloneMap;
	}

	public class IgnoreDTDEntityResolver implements EntityResolver {
		@Override
		public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
			return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
		}
	}
}
